using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class SceneManager : MonoBehaviour
{
    public static SceneManager Instance;

    [Header("UI References")]
    public RawImage backgroundImage;
    public Texture startingBackground;
    public Transform characterSpawnArea;
    public Transform locationSpawnArea;
    public GameObject goBackButton;
    public GameObject npcPrefab;
    public GameObject locationPrefab;
    public GameObject navigationPanel;   // contains NPC + location buttons
    public GameObject conversationPanel; // contains chat UI
    public Image characterPortrait; // contains chat UI

    [Header("Scene Data")]
    private Stack<SceneData> sceneStack = new Stack<SceneData>();
    private SceneData currentScene;
    public SceneData startScene;
    private Dictionary<string, SceneData> sceneRegistry = new Dictionary<string, SceneData>();


    void Awake()
    {
        if (Instance == null)
        {
            Instance = this;
            DontDestroyOnLoad(gameObject);
        }
        else
        {
            Destroy(gameObject);
        }
    }

    private void Start()
    {
        startScene.exits.Clear();
        EnterScene(startScene);
    }

    // --- Public API ---
    public void RegisterScene(string name, SceneData scene)
    {
        if (!sceneRegistry.ContainsKey(name))
        {
            sceneRegistry[name] = scene;
        }
    }


    private Dictionary<string, SceneData> pendingOrigins = new Dictionary<string, SceneData>();

    public void RegisterPendingScene(string name, SceneData scene, SceneData originScene = null)
    {
        if (!sceneRegistry.ContainsKey(name))
        {
            sceneRegistry[name] = scene;
        }

        // Store where the exit should appear
        if (originScene != null)
            pendingOrigins[name] = originScene;
        else if (currentScene != null)
            pendingOrigins[name] = currentScene;
    }

    public SceneData GetScene(string name)
    {
        return sceneRegistry.ContainsKey(name) ? sceneRegistry[name] : null;
    }


    public void EnterScene(SceneData newScene)
    {
        if (currentScene != null)
        {
            sceneStack.Push(currentScene);
        }

        currentScene = newScene;
        RenderScene(false);
    }

    public void GoBack()
    {
        if (sceneStack.Count > 0)
        {
            currentScene = sceneStack.Pop();
            RenderScene(false);
        }
    }

    public void StartConversation(NPCData npc)
    {
        navigationPanel.SetActive(false);
        conversationPanel.SetActive(true);
        characterPortrait.sprite = npc.portrait;

        Debug.Log("Starting conversation with " + npc.displayName);

        //  Clear visual chat text each time
        if (ChatManager.Instance != null)
            ChatManager.Instance.ClearChat();

        //  Begin per-NPC conversation
        if (IWGAI.Demo.LLMParser.Instance != null)
        {
            IWGAI.Demo.LLMParser.Instance.BeginConversation(npc, GetCurrentScene());
        }
    }


    public void AddExitToScene(string locationName, bool keepConversation = false)
    {
        if (!sceneRegistry.ContainsKey(locationName)) return;

        SceneData origin = null;
        if (pendingOrigins.ContainsKey(locationName))
            origin = pendingOrigins[locationName];

        if (origin == null) origin = currentScene;
        if (origin == null) return;

        if (!origin.exits.Contains(locationName))
            origin.exits.Add(locationName);

        if (origin == currentScene)
            RenderScene(keepConversation);
    }


    public void EndConversation()
    {
        conversationPanel.SetActive(false);
        navigationPanel.SetActive(true);
    }


    public SceneData GetCurrentScene()
    {
        return currentScene;
    }
    public void RegisterPendingScene(string name, SceneData scene)
    {
        if (!sceneRegistry.ContainsKey(name))
        {
            sceneRegistry[name] = scene;
        }
    }


    // --- Internal ---
    public void RenderScene(bool stayInConversation)
    {
        if (sceneStack.Count > 0)
            goBackButton.SetActive(true);
        else
            goBackButton.SetActive(false);

        // Always assign background
        if (currentScene.background != null)
            backgroundImage.texture = currentScene.background;
        else
            backgroundImage.texture = startingBackground; 

        foreach (Transform child in characterSpawnArea)
            Destroy(child.gameObject);
        foreach (Transform child in locationSpawnArea)
            Destroy(child.gameObject);

        foreach (NPCData npc in currentScene.npcs)
        {
            GameObject npcObj = Instantiate(npcPrefab, characterSpawnArea);
            npcObj.GetComponentInChildren<Image>().sprite = npc.portrait;
            npcObj.GetComponent<Button>().onClick.AddListener(() => StartConversation(npc));
        }

        foreach (string exit in currentScene.exits)
        {
            GameObject exitBtn = Instantiate(locationPrefab, locationSpawnArea);
            exitBtn.GetComponentInChildren<TMPro.TMP_Text>().text = exit;
            exitBtn.GetComponent<Button>().onClick.AddListener(() =>
            {
                SceneData targetScene = GetScene(exit);
                if (targetScene != null)
                    EnterScene(targetScene);
            });
        }

        if (!stayInConversation)
        {
            navigationPanel.SetActive(true);
            conversationPanel.SetActive(false);
        }
    }


}
